package com.myutils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.SocketException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.ResourceBundle;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;

/**
 * @author Lan
 * @Company 上海全景数字技术有限公司
 */
public class FtpTools {

	public FTPClient ftpClient;

	private String logPath;

	public FtpTools() {
		ResourceBundle resources = ResourceBundle.getBundle("file");
		logPath = resources.getString("logPath");
		writeLog("--------------------------");
		writeLog("--start ftp client");
	}

	public boolean connect(String ip, int port) {
		writeLog("--connect " + ip + ": " + port);
		boolean connected = false;
		ftpClient = new FTPClient();
		try {
			ftpClient.connect(ip, port);
			int reply = ftpClient.getReplyCode();
			writeLog("server reply: " + reply);
			if (reply == FTPReply.SERVICE_READY) {//220
				connected = true;
				writeLog("connect success");
			}
		} catch (SocketException e) {
			writeLog("connect socket error" + e.getMessage());
		} catch (IOException e) {
			writeLog("connect io error" + e.getMessage());
		}
		return connected;
	}

	public boolean login(String user, String pass) {
		writeLog("--login " + user + "@" + pass);
		boolean login = false;
		if (ftpClient == null) {
			writeLog("not connected");
			return false;
		}
		try {
			ftpClient.login(user, pass);
			int reply = ftpClient.getReplyCode();
			writeLog("server reply: " + reply);
			if (reply == FTPReply.USER_LOGGED_IN) {//230
				login = true;
				writeLog("login success");
			}
		} catch (IOException e) {
			writeLog("login io error" + e.getMessage());
		}
		return login;
	}

	/**
	 * �ϴ������ļ�
	 * 
	 * @param localPath
	 *            �����ļ�·��
	 * @param remotePath
	 *            Զ��·��
	 * @return true �ϴ��ɹ���false �ϴ�ʧ��
	 */
	public boolean uploadFile(String localPath, String remotePath) {
		writeLog("--upload " + localPath + " to " + remotePath);
		boolean uploaded = false;

		File localFile = new File(localPath);

		// binaryģʽ
		try {
			writeLog("binary mode");
			ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
		} catch (IOException e) {
			writeLog("binary io error: " + e.getMessage());
			return false;
		}

		// passiveģʽ
		writeLog("passive mode");
		ftpClient.enterLocalPassiveMode();

		// stream����ģʽ
		try {
			writeLog("stream transfer mode");
			ftpClient.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);
		} catch (IOException e) {
			writeLog("stream transfer mode io error: " + e.getMessage());
			return false;
		}

		// ��ȡ�����ļ�����
		InputStream input;
		try {
			writeLog("read local file to stream");
			input = new FileInputStream(localFile);
		} catch (FileNotFoundException e) {
			writeLog("local file not find: " + e.getMessage());
			return false;
		}

		// ���ʹ���Զ��Ŀ¼
		if (!isRemoteDirExist(remotePath)) {
			writeLog("mkdir: " + remotePath);
			try {
				makeDirs(remotePath);
			} catch (IOException e) {
				writeLog("mkdir error: " + e.getMessage());
				return false;
			}
		}

		// ����Զ��Ŀ¼
		try {
			writeLog("cd: " + remotePath);
			ftpClient.changeWorkingDirectory(remotePath);
		} catch (IOException e) {
			writeLog("cd error: " + e.getMessage());
			return false;
		}

		// �ϴ��ļ�
		try {
			writeLog("upload");
			ftpClient.storeFile(localFile.getName(), input);
			int reply = ftpClient.getReplyCode();
			writeLog("server reply: " + reply);
			if (reply == FTPReply.CLOSING_DATA_CONNECTION) {//226
				uploaded = true;
				writeLog("upload success");
			}
		} catch (IOException e) {
			writeLog("upload io error: " + e.getMessage());
		}

		// �ر��ļ���
		try {
			input.close();
		} catch (IOException e) {
			writeLog("close inputstream error: " + e.getMessage());
		}

		return uploaded;
	}

	/**
	 * �������ļ�
	 * 
	 * @param localPath
	 *            �����ļ�·��
	 * @param remotePath
	 *            Զ��·��
	 * @return true �ϴ��ɹ���false �ϴ�ʧ��
	 */
	public boolean createFile(String remoteFile) {
		writeLog("--createFile " + remoteFile);
		boolean created = false;

		String filename = remoteFile;
		if (remoteFile.indexOf("/") != -1) {
			filename = remoteFile.substring(remoteFile.lastIndexOf("/") + 1,
					remoteFile.length());
		}

		String remotePath = "/";
		if (remoteFile.indexOf("/") != -1) {
			remotePath = remoteFile.substring(0, remoteFile.lastIndexOf("/"));
		}

		// binaryģʽ
		try {
			writeLog("binary mode");
			ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
		} catch (IOException e) {
			writeLog("binary io error: " + e.getMessage());
			return false;
		}

		// passiveģʽ
		writeLog("passive mode");
		ftpClient.enterLocalPassiveMode();

		// stream����ģʽ
		try {
			writeLog("stream transfer mode");
			ftpClient.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);
		} catch (IOException e) {
			writeLog("stream transfer mode io error: " + e.getMessage());
			return false;
		}

		// ��ȡ�����ļ�����
		InputStream input;
		try {
			writeLog("create empty file to stream");
			File emptyFile = File.createTempFile(filename, ".fin");
			input = new FileInputStream(emptyFile);
		} catch (FileNotFoundException e) {
			writeLog("create empty file error: " + e.getMessage());
			return false;
		} catch (IOException e) {
			writeLog("create empty file error: " + e.getMessage());
			return false;
		}
		// stream����ģʽ
		try {
			writeLog("stream transfer mode");
			ftpClient.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);
		} catch (IOException e) {
			writeLog("stream transfer mode io error: " + e.getMessage());
			return false;
		}
		
		// ���ʹ���Զ��Ŀ¼
		if (!isRemoteDirExist(remotePath)) {
			writeLog("mkdir: " + remotePath);
			try {
				makeDirs(remotePath);
			} catch (IOException e) {
				writeLog("mkdir error: " + e.getMessage());
				return false;
			}
		}

		// ����Զ��Ŀ¼
		try {
			writeLog("cd: " + remotePath);
			ftpClient.changeWorkingDirectory(remotePath);
		} catch (IOException e) {
			writeLog("cd error: " + e.getMessage());
			return false;
		}

		// �����ļ�
		try {
			writeLog("create: " + filename);
			created = ftpClient.storeFile(filename, input);

			int reply = ftpClient.getReplyCode();
			writeLog("server reply: " + reply);
			if (reply == FTPReply.CLOSING_DATA_CONNECTION) {//226
				created = true;
				writeLog("create success");
			}
		} catch (IOException e) {
			writeLog("create error: " + e.getMessage());
			return false;
		}

		return created;
	}

	/**
	 * Զ��Ŀ¼�Ƿ����
	 * 
	 * @param dirPath
	 * @return �Ƿ����
	 */
	public boolean isRemoteDirExist(String dirPath) {
		boolean exist = false;
		try {
			exist = ftpClient.changeWorkingDirectory(dirPath);
		} catch (IOException e) {
		}
		return exist;
	}

	/**
	 * �����༶Ŀ¼
	 * 
	 * @param dirPath
	 * @return �Ƿ�ɹ�
	 * @throws IOException
	 */
	public boolean makeDirs(String dirPath) throws IOException {
		String temp = "";
		String currentDir = "";
		String subDir = dirPath;
		if (subDir.startsWith("/")) {
			subDir = subDir.substring(1);
		}
		ftpClient.changeWorkingDirectory("/");
		while (!subDir.equals("")) {
			ftpClient.changeWorkingDirectory(currentDir);
			if (subDir.indexOf("/") != -1) {
				temp = subDir.substring(0, subDir.indexOf("/"));
				subDir = subDir.substring(temp.length() + 1);
				currentDir += "/" + temp;
			} else {
				temp = subDir;
				subDir = "";
			}
			ftpClient.makeDirectory(temp);
		}
		if (isRemoteDirExist(dirPath)) {
			return true;
		} else {
			return false;
		}
	}
	
	public void close(){
		try {
			writeLog("close ftp");
			ftpClient.disconnect();
		} catch (IOException e) {
			writeLog("close ftp error: " + e.getMessage());
		}
	}

	/**
	 * ׷���ı�д����־�ļ�
	 * 
	 * @param content
	 *            ����
	 * @throws IOException
	 */
	public void writeLog(String content) {

		Date date = new Date();
		SimpleDateFormat fileFormat = new SimpleDateFormat("yyyy-MM-dd");
		SimpleDateFormat dateFormat = new SimpleDateFormat(
				"yyyy-MM-dd hh:mm:ss");
		String day = fileFormat.format(date);
		String now = dateFormat.format(date);
		String fileName = logPath + "log_" + day + ".txt";
		content = "[" + now + "] " + content;
		File file = new File(fileName);
		if (!file.exists()) {
			file.getParentFile().mkdirs();
		}
		RandomAccessFile rf;
		try {
			rf = new RandomAccessFile(fileName, "rw");
			rf.seek(rf.length());// ��ָ���ƶ����ļ�ĩβ
			rf.writeBytes("\r\n" + content);
			rf.close();// �ر��ļ���
		} catch (FileNotFoundException e) {
		} catch (IOException e) {
		}
	}

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		FtpTools ftp = new FtpTools();
		ftp.connect("192.168.188.18", 21);
		ftp.login("xiaoxiao", "xiaoxiao");
//		ftp.uploadFile("C:\\zip.jar", "/files2/1/2/3/4/5");
		ftp.createFile("/files2/1/2/3/4/5/33.txt");
		ftp.close();
	}

}

